import {
  Body,
  Controller,
  Del,
  Get,
  Inject,
  Post,
  Put,
  Query,
} from '@midwayjs/core';
import { AreaService } from '../../service/area/area.service';
import { Validate } from '@midwayjs/validate';
import {
  ListParamsValidator,
  StrIdNullValidator,
  StrIdValidator,
} from '../../validator';
import {
  AreaCodeValidator,
  EditAreaValidator,
  SaveAreaValidator,
} from '../../validator/area/area';
import { RedisService } from '@midwayjs/redis';
import { RedisKeys } from '../../construct/redisKeys';
import { jsonStringify, jsonStringify2json } from '../../utils/toolsHelper';
import { AreaSchema } from '../../schema';
import { isNotEmpty } from '../../utils/isHelper';
import { BadRequestError } from '@midwayjs/core/dist/error/http';

@Controller('/area', { tagName: '' })
export class AreaController {
  @Inject()
  areaService: AreaService;

  @Inject()
  redisService: RedisService;

  @Post('/list', { summary: '列表' })
  @Validate()
  async list(@Body() body: ListParamsValidator<AreaSchema>) {
    const { search } = body;
    Object.assign(search, {
      parent: {
        name: search?.parent?.name ?? '',
      },
    });
    const data = await this.areaService.list(body);
    return Object.assign(data, body);
  }

  @Post('/save', { summary: '保存' })
  @Validate()
  async save(@Body() body: SaveAreaValidator) {
    await this.redisService.del(RedisKeys.AREA_TREES_LIST);
    return await this.areaService.save(body);
  }

  @Get('/info', { summary: '信息' })
  @Validate()
  async info(@Query() body: StrIdValidator) {
    return await this.areaService.info(body.id);
  }

  @Del('/remove', { summary: '删除' })
  @Validate()
  async remove(@Query() body: StrIdValidator) {
    const hasChildren = await this.areaService.findMoreByFields({
      parent: { id: body.id },
    });
    if (isNotEmpty(hasChildren)) {
      throw new BadRequestError('存在子级数据无法删除');
    }
    await this.redisService.del(RedisKeys.AREA_TREES_LIST);
    return await this.areaService.remove(body.id);
  }

  @Del('/delete', { summary: '（真）删除' })
  @Validate()
  async realRemove(@Query() body: StrIdValidator) {
    const hasChildren = await this.areaService.findMoreByFields({
      parent: { id: body.id },
    });
    if (isNotEmpty(hasChildren)) {
      throw new BadRequestError('存在子级数据无法删除');
    }
    await this.redisService.del(RedisKeys.AREA_TREES_LIST);
    return await this.areaService.realRemove(body.id);
  }

  @Put('/edit', { summary: '编辑' })
  @Validate()
  async edit(@Query() query: StrIdValidator, @Body() body: EditAreaValidator) {
    const area = await this.areaService.info(query.id);
    if (!isNotEmpty(body.parent.id)) {
      delete body.parent;
    }
    Object.assign(area, body);
    await this.redisService.del(RedisKeys.AREA_TREES_LIST);
    return await this.areaService.save(area);
  }

  @Get('/trees', { summary: '区域树' })
  @Validate()
  async trees() {
    const cacheAreas = await this.redisService.get(RedisKeys.AREA_TREES_LIST);
    if (cacheAreas) {
      return { list: jsonStringify2json(cacheAreas) };
    } else {
      const list = await this.areaService.trees();
      await this.redisService.set(
        RedisKeys.AREA_TREES_LIST,
        jsonStringify(list)
      );
      return { list };
    }
  }

  @Get('/infoByCode', { summary: '通过code查询数据' })
  @Validate()
  async infoByCode(@Query() query: AreaCodeValidator) {
    return await this.areaService.findByFields({ code: query.code });
  }

  @Get('/byParentGetChildren', { summary: '传入父级获取子级' })
  @Validate()
  async byParentGetChildren(@Query() query: StrIdNullValidator) {
    return await this.areaService.findByParent(query);
  }
}
